/*
 * MeasuredPoint.java
 *
 * Created on 23 mai 2006, 09:14
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package courselog.gpsutils;

import ewe.sys.Convert;
import ewe.sys.Time;
import ewe.util.Copyable;
import courselog.gpsutils.jcoord.RefEll;

/**
 * Measured location point from a GPS.
 * Gathers all collected data and computed also.
 * @author C. Rigal
 */
public class MeasuredPoint extends GeoPoint implements Copyable {
    
    /**
     * Altitude of the Mean Sea Level to the geoid (m).
     */
    public double altGeoid;
    
    /**
     * Date generated in GPS format (DDMMYY).
     */
    public int date;

    /**
     * Measured time as a Time object for difference of dates calculations.
     * @see MeasuredPoint#computeTime()
     */
    public Time measureTime=new Time();
    
    /**
     * Heading in degrees.
     */
    public double heading;
    
    /**
     * Measured speed at that point (km/h)
     */
    public double speed;
    
    /**
     * UTC Time provided by the GPS (HHMMSS.SSS)
     */
    public double time;

    /**
     * Number of satellites used to compute the point.
     */
    public int satsInSolution = 0;
    
    /**
     * Horizontal Dilution Of Precision
     */
    public double hDOP = 0;

    /**
     * Vertical Dilution Of Precision.
     */
    public double vDOP = 0;

    /**
     * True if was computed by differential GPS.
     * Configuration of receiver not yet implemented.
     */
    public boolean isDifferential;

    /**
     * Creates a new empty instance of MeasuredPoint.
     * The new point is initialised.
     */
    public MeasuredPoint() {
        initialise();
    }
    
    /**
     * Put default (unusable values in this object so that it will be ready for reuse.
     */
    public void initialise() {
        super.initialise();
        this.measureTime= new Time();
        time=measureTime.hour*10000+measureTime.minute*100+measureTime.second;
        date=measureTime.day*10000+measureTime.month*100+(measureTime.year-2000);
        altGeoid=-1;
        heading=-1;
        speed=-1;
    }
    
    /**
     * Copy all elements of this point in a new instance.
     * The measured time is also copied in a new Time object.
     * @return New MeasuredPoint with identical data
     * @see ewe.util.Copyable#getCopy
     */
    public Object getCopy() {
        MeasuredPoint pt=new MeasuredPoint();
        pt.copyFrom(this);
        return pt;
    }
    
    /**
     * Copy all elements of point param into <b>this</b> instance.
     * @param param Point to copy from.
     */
    public void copyFrom(Object param) {
        if(!(param instanceof MeasuredPoint)) {
            return;
        }
        MeasuredPoint pt= (MeasuredPoint) param;
        super.copyFrom(param);
        time=pt.time;
        altGeoid=pt.altGeoid;
        date=pt.date;
        measureTime=new Time();
        measureTime.copyFrom(pt.measureTime);
        heading=pt.heading;
        speed=pt.speed;
        satsInSolution=pt.satsInSolution;
        hDOP=pt.hDOP;
        vDOP=pt.vDOP;
        isDifferential=pt.isDifferential;
    }
        
    /**
     * Compute the difference of time of measurement in seconds (decimal)
     * between this point and the given point.
     * Positive when this point is later than <I>pointTo</I>.
     * @param pointTo Point of comparison. Its measuredTime field must 
     * be up to date.
     * @see MeasuredPoint#computeTime()
     * @return The time difference in seconds (with 3 decimals).
     */
    public double timeTo(MeasuredPoint pointTo) {
        return (this.measureTime.getTime()-pointTo.measureTime.getTime())/1000.0d;
    }
    
    /**
     * Compute the measuredTime ewe.sys.Time object of this MeasuredPoint.
     */
    public void computeTime() {
        int vTmp = (int) (date/10000);
        measureTime.day= vTmp ;
        vTmp = date-vTmp*10000;
        measureTime.month = (int) (vTmp/100);
        measureTime.year = (vTmp-measureTime.month*100)+2000;
        
        int iTime = (int) time;
        vTmp = (int) (iTime/10000);
        measureTime.hour= vTmp;
        vTmp = iTime-vTmp*10000;
        measureTime.minute=(int) (vTmp/100);
        vTmp = vTmp-(measureTime.minute*100);
        measureTime.second= (int) vTmp;
        measureTime.millis = (int) ((time-iTime)*1000);
    }

    /**
     * Formats the heading of this point.
     * @see Converters#formatHeading(double)
     * @return Formatted heading.
     */
    public String formatHeading() {
        return Converters.formatHeading(heading);
    }
    
    /**
     * Formats the speed of this point.
     * @return Formatted speed.
     * @see Converters#formatSpeed(double)
     */
    public String formatSpeed() {
        return Converters.formatSpeed(speed);
    }
}
